﻿using SignalBox.Core.Data;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace SignalBox.Core.Model
{
    public class TrackLayout
    {
        private String fileName;

        public static int PIXELSPERCELL = 16;

        private bool editMode;
        
        private Dictionary<int, Dictionary<int, TrackCell>> layout;

        private List<TrackText> labels;

        public List<TrackText> Labels
        {
            get { return labels; }
        }

        public TrackCell FindLocation(string name)
        {
            string locName = name;
            string platform = "";

            if (name.IndexOf("@") > 0)
            {
                string[] parts = name.Split("@".ToCharArray());
                name = parts[0];
                platform = parts[1];
            }

            foreach (int x in layout.Keys)
            {
                foreach (int y in layout[x].Keys)
                {
                    TrackCell tc = layout[x][y];
                    if (tc.Name == locName && tc.Platform == platform)
                        return tc;
                }
            }

            return null;

        }

        public List<String> getLocations()
        {
            var locations = new List<String>();

            foreach (int x in layout.Keys)
            {
                foreach (int y in layout[x].Keys)
                {
                    var tc = layout[x][y];
                    if (!String.IsNullOrEmpty(tc.Name))
                    {
                        if (!locations.Contains(tc.Name))
                        {
                            locations.Add(tc.Name);
                        }
                        if (!String.IsNullOrEmpty(tc.Platform))
                        {
                            if (!locations.Contains(tc.Name + "@" + tc.Platform))
                            {
                                locations.Add(tc.Name + "@" + tc.Platform);
                            }
                        }
                    }
                }
            }

            return locations;
        }

        public TrackLayout(bool isEditMode)
        {
            layout = new Dictionary<int, Dictionary<int, TrackCell>>();
            labels = new List<TrackText>();
            editMode = isEditMode;
            ShowGrid = true;
            Cols = 300;
            Rows = 100;
        }

        public bool HasModifications
        {
            get;
            set;
        }


        public bool HasFileName()
        {
            return fileName != null && fileName != string.Empty;
        }

        public int Cols
        {
            get;
            set;
        }
        public int Rows
        {
            get;
            set;
        }


        public void Save(FileInfo f)
        {
            fileName = f.FullName;
            DataLayer.Instance.TrackFile = fileName;

            save();
        }

        public void save()
        {
            var li = new LayoutInfo();
            li.Name = LayoutName;
            li.SizeX = Cols;
            li.SizeY = Rows;
            li.Author = Author;
            li.Description = Description;

            DataLayer.Instance.LayoutInfo = li;
            

            var list = new List<Track>();

            foreach (int x in layout.Keys)
            {
                foreach (int y in layout[x].Keys)
                {
                    var tc = layout[x][y];

                    var t = new Track();
                    t.X = tc.X;
                    t.Y = tc.Y;
                    t.Type = (int)tc.Type;
                    t.Length = tc.Length;
                    t.MaxSpeedLeft = tc.MaxSpeedLeft;
                    t.MaxSpeedRight = tc.MaxSpeedRight;
                    if (tc.TrackCellType.Category == "SIGNAL")
                    {
                        t.SignalAspect = (int)tc.SignalAspect;
                    }
                    if (tc.LinkedCell != null)
                    {
                        t.LinkX = tc.LinkedCell.X;
                        t.LinkY = tc.LinkedCell.Y;
                    }
                    else
                    {
                        t.LinkX = -1;
                        t.LinkY = -1;
                    }
                    t.Name = tc.Name;
                    t.Platform = tc.Platform;
                    list.Add(t);
                }
            }

            DataLayer.Instance.TrackList = list;
            DataLayer.Instance.TrackTexts = Labels;
            DataLayer.Instance.Save();

            HasModifications = false;
        }

        public void loadLayout(FileInfo f)
        {
            fileName = f.FullName;

            DataLayer.Instance.TrackFile = fileName;

            layout = new Dictionary<int, Dictionary<int, TrackCell>>();

            var i = DataLayer.Instance.LayoutInfo;
            Rows = i.SizeY;
            Cols = i.SizeX;
            LayoutName = i.Name;
            Author = i.Author;
            Description = i.Description;

            var list = DataLayer.Instance.TrackList;

            foreach (Track t in list)
            {
                var tc = new TrackCell(editMode);
                tc.X = t.X;
                tc.Y = t.Y;
                tc.Type = (TRACKCELLTYPE)t.Type;
                tc.Length = t.Length;
                tc.MaxSpeedLeft = t.MaxSpeedLeft;
                tc.MaxSpeedRight = t.MaxSpeedRight;
                tc.Name = t.Name;
                if (tc.TrackCellType.Category == "SIGNAL")
                {
                    tc.SignalAspect = (SIGNALASPECTTYPE)t.SignalAspect;
                }
                tc.Platform = t.Platform;
                updateCell(tc.X, tc.Y, tc);
            }

            foreach (Track t in list)
            {
                if (t.LinkX > -1 && t.LinkY > -1)
                {
                    var tc = getCell(t.X, t.Y);
                    var link = getCell(t.LinkX, t.LinkY);
                    tc.LinkedCell = link;
                    link.LinkedCell = tc;
                }
            }

            labels = DataLayer.Instance.TrackTexts;
        }

        public void updateCell(int x, int y, TrackCell tc)
        {
            if (!layout.ContainsKey(x))
            {
                layout[x] = new Dictionary<int, TrackCell>();
            }

            layout[x][y] = tc;

            HasModifications = true;
        }

        public void markCellSelected(int x, int y, bool selected)
        {
            var tc = getCell(x, y);
            if (tc != null)
            {
                tc.Selected = selected;
            }
        }

        public bool linkCells(int x1, int y1, int x2, int y2)
        {
            var cell1 = getCell(x1, y1);
            var cell2 = getCell(x2, y2);

            var canLink = false;

            if (cell1.HasDirection(DIRECTION.N) && cell2.HasDirection(DIRECTION.S))
            {
                canLink = true;
            }
            if (cell1.HasDirection(DIRECTION.S) && cell2.HasDirection(DIRECTION.N))
            {
                canLink = true;
            }
            if (cell1.HasDirection(DIRECTION.E) && cell2.HasDirection(DIRECTION.W))
            {
                canLink = true;
            }
            if (cell1.HasDirection(DIRECTION.W) && cell2.HasDirection(DIRECTION.E))
            {
                canLink = true;
            }
            if (cell1.HasDirection(DIRECTION.NE) && cell2.HasDirection(DIRECTION.SW))
            {
                canLink = true;
            }
            if (cell1.HasDirection(DIRECTION.NW) && cell2.HasDirection(DIRECTION.SE))
            {
                canLink = true;
            }
            if (cell1.HasDirection(DIRECTION.SE) && cell2.HasDirection(DIRECTION.NW))
            {
                canLink = true;
            }
            if (cell1.HasDirection(DIRECTION.SW) && cell2.HasDirection(DIRECTION.NE))
            {
                canLink = true;
            }
            if (canLink)
            {
                if (cell1.LinkedCell != null)
                {
                    cell1.LinkedCell.LinkedCell = null;
                }
                if (cell2.LinkedCell != null)
                {
                    cell2.LinkedCell.LinkedCell = null;
                }
                cell1.LinkedCell = cell2;
                cell2.LinkedCell = cell1;
            }

            HasModifications = canLink;

            return canLink;
        }

        public void removeCell(int x, int y)
        {
            if (layout.ContainsKey(x))
            {
                if (layout[x].ContainsKey(y))
                {
                    layout[x].Remove(y);

                    HasModifications = true;
                }
            }
        }

        public TrackCell getCell(int x, int y)
        {
            if (!layout.ContainsKey(x))
            {
                return null;
            }
            if (!layout[x].ContainsKey(y))
            {
                return null;
            }
            return layout[x][y];
        }


        public bool ShowGrid
        {
            get;
            set;
        }

        public string LayoutName
        {
            get;
            set;
        }

        public string Author
        {
            get;
            set;
        }

        public string Description
        {
            get;
            set;
        }
    }
}
